package fun.easycode.webterminal.service.impl;

import com.github.bytesops.jproxy.proxy.ProxyConfig;
import com.github.bytesops.jproxy.proxy.ProxyType;
import com.github.bytesops.jproxy.server.HttpProxyServer;
import fun.easycode.webterminal.common.contract.DynamicOperate;
import fun.easycode.webterminal.common.contract.PageDTO;
import fun.easycode.webterminal.common.contract.R;
import fun.easycode.webterminal.dao.ProxyTransform;
import fun.easycode.webterminal.dao.ProxyTransformRepository;
import fun.easycode.webterminal.dao.TransformType;
import fun.easycode.webterminal.service.ProxyTransformService;
import fun.easycode.webterminal.service.cmd.ProxyTransformPageQry;
import fun.easycode.webterminal.service.cmd.ProxyTransformSaveCmd;
import fun.easycode.webterminal.service.cmd.ProxyTransformSaveCmdAssembler;
import fun.easycode.webterminal.service.dto.ProxyTransformDTO;
import fun.easycode.webterminal.service.dto.ProxyTransformDTOAssembler;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Service
public class ProxyTransformServiceImpl implements ProxyTransformService {

    @Resource
    private ProxyTransformRepository proxyTransformRepository;

    private final Map<String, HttpProxyServer> proxyMap = new ConcurrentHashMap<>();
    private final Map<String, String> startMap = new ConcurrentHashMap<>();
    // 使用ConcurrentHashMap来存储每个ID对应的锁对象
    private final ConcurrentHashMap<String, Lock> locks = new ConcurrentHashMap<>();


    @Override
    public R<String> delete(String id) {
        proxyTransformRepository.removeById(id);
        return R.message("删除成功");
    }

    @Override
    public R<ProxyTransformDTO> getById(String id) {
        ProxyTransform proxyTransform = proxyTransformRepository.getById(id);

        if (proxyTransform == null) {
            return R.error("代理转换不存在");
        }

        return R.success(ProxyTransformDTOAssembler.INSTANCE.to(proxyTransform));
    }

    @Override
    public R<PageDTO<ProxyTransformDTO>> page(ProxyTransformPageQry cmd) {
        cmd.validate();
        PageDTO<ProxyTransformDTO> page = DynamicOperate.page(cmd, proxyTransformRepository.getBaseMapper(), ProxyTransformDTOAssembler.INSTANCE::to);

        page.getData().forEach(proxyTransformDTO -> {
            proxyTransformDTO.setStart(startMap.containsKey(proxyTransformDTO.getId()));
        });

        return R.success(page);
    }

    @Override
    public R<String> save(ProxyTransformSaveCmd cmd) {

        cmd.validate();

        ProxyTransform tunnel = ProxyTransformSaveCmdAssembler.INSTANCE.to(cmd);

        boolean r = proxyTransformRepository.saveOrUpdate(tunnel);

        return r ? R.message("保存成功!") : R.error("保存失败!");
    }

    @Override
    public R<String> start(String id) {

        Lock lock = getLock(id);
        lock.lock();
        try {
            if (proxyMap.containsKey(id)) {
                return R.error("该代理转换已启动");
            }

            ProxyTransform proxyTransform = proxyTransformRepository.getById(id);

            if (proxyTransform == null) {
                return R.error("代理转换不存在");
            }

            ProxyType type = proxyTransform.getType() == TransformType.SOCKET4 ? ProxyType.SOCKS4 : ProxyType.SOCKS5;

            // 使用 socks5 二级代理
            HttpProxyServer httpProxyServer = new HttpProxyServer()
                    .proxyConfig(new ProxyConfig(type, proxyTransform.getSocketIp(), proxyTransform.getSocketPort()));

            proxyMap.put(id, httpProxyServer);

            new Thread(() -> {
                httpProxyServer.start(proxyTransform.getPort());
            }).start();

            startMap.put(id, id);

        } finally {
            lock.unlock();
        }

        return R.message("启动成功");
    }

    @Override
    public R<String> stop(String id) {
        Lock lock = getLock(id);
        lock.lock();

        try {
            if (!proxyMap.containsKey(id)) {
                return R.error("该代理转换未启动");
            }

            HttpProxyServer httpProxyServer = proxyMap.get(id);

            httpProxyServer.close();

            proxyMap.remove(id);
            startMap.remove(id);

        } finally {
            lock.unlock();
        }
        return R.message("停止成功");
    }

    /**
     * 获取指定ID的锁
     *
     * @param id 需要加锁的ID
     * @return 返回对应ID的锁对象
     */
    public Lock getLock(String id) {
        // 使用computeIfAbsent方法来确保每个ID只有一个锁对象
        return locks.computeIfAbsent(id, k -> new ReentrantLock());
    }
}
